{
 "cells": [
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T07:48:17.348373Z",
     "start_time": "2025-01-10T07:47:46.799903Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import pulp\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "def optimize_containers(df, wt, vt):\n",
    "    # 获取唯一的目的地\n",
    "    destinations = df['d'].unique()\n",
    "    \n",
    "    # 创建问题\n",
    "    prob = pulp.LpProblem(\"Container_Optimization\", pulp.LpMinimize)\n",
    "    \n",
    "    # 计算需要的最小集装箱数（向上取整）\n",
    "    min_containers_volume = int(np.ceil(sum(df['v'] * df['n']) / vt))\n",
    "    min_containers_weight = int(np.ceil(sum(df['w'] * df['n']) / wt))\n",
    "    min_containers = max(min_containers_volume, min_containers_weight)\n",
    "    # 够大，不过最好别太大\n",
    "    max_containers = int(min_containers * 1.5)\n",
    "    \n",
    "    print(f\"按体积计算的最小集装箱数: {min_containers_volume}\")\n",
    "    print(f\"按重量计算的最小集装箱数: {min_containers_weight}\")\n",
    "    print(f\"理论最小集装箱数: {min_containers}\")\n",
    "    \n",
    "    # 决策变量\n",
    "    # y[k]: 是否使用第k个集装箱\n",
    "    y = pulp.LpVariable.dicts(\"container\",\n",
    "                             range(max_containers),\n",
    "                             cat='Binary')\n",
    "    \n",
    "    # x[i,k]: 货物i分配到集装箱k的数量\n",
    "    x = pulp.LpVariable.dicts(\"allocation\",\n",
    "                             ((i, k) for i in range(len(df)) \n",
    "                              for k in range(max_containers)),\n",
    "                             lowBound=0,\n",
    "                             cat='Integer')  # 改为整数变量\n",
    "    \n",
    "    # z[k,d]: 集装箱k是否用于目的地d\n",
    "    z = pulp.LpVariable.dicts(\"destination\",\n",
    "                             ((k,d) for k in range(max_containers) \n",
    "                              for d in destinations),\n",
    "                             cat='Binary')\n",
    "    \n",
    "    # 目标函数：最小化使用的集装箱数量\n",
    "    prob += pulp.lpSum(y[k] for k in range(max_containers))\n",
    "    \n",
    "    # 约束条件\n",
    "    # 1. 每种货物必须被完全分配\n",
    "    for i in range(len(df)):\n",
    "        prob += pulp.lpSum(x[i,k] for k in range(max_containers)) == df.iloc[i]['n']\n",
    "    \n",
    "    # 2. 每个集装箱的重量和体积限制\n",
    "    for k in range(max_containers):\n",
    "        # 重量约束\n",
    "        prob += pulp.lpSum(x[i,k] * df.iloc[i]['w'] for i in range(len(df))) <= wt * y[k]\n",
    "        # 体积约束\n",
    "        prob += pulp.lpSum(x[i,k] * df.iloc[i]['v'] for i in range(len(df))) <= vt * y[k]\n",
    "    \n",
    "    # 3. 目的地约束\n",
    "    for k in range(max_containers):\n",
    "        # 每个集装箱最多只能服务于一个目的地\n",
    "        prob += pulp.lpSum(z[k,d] for d in destinations) <= y[k]\n",
    "        # 如果集装箱k装了目的地为d的货物，则z[k,d]必须为1\n",
    "        for i in range(len(df)):\n",
    "            for d in destinations:\n",
    "                if df.iloc[i]['d'] == d:\n",
    "                    prob += x[i,k] <= df.iloc[i]['n'] * z[k,d]\n",
    "    \n",
    "    # 求解\n",
    "    print(\"开始求解...\")\n",
    "    solver = pulp.PULP_CBC_CMD(msg=True, timeLimit=30)  # 增加求解时间\n",
    "    status = prob.solve(solver)\n",
    "    print(f\"求解状态: {pulp.LpStatus[status]}\")\n",
    "    \n",
    "    if status != pulp.LpStatusOptimal:\n",
    "        print(\"未找到最优解！\")\n",
    "        return None\n",
    "    \n",
    "    # 获取结果\n",
    "    results = []\n",
    "    for k in range(max_containers):\n",
    "        if pulp.value(y[k]) > 0.5:  # 使用了这个集装箱\n",
    "            container_items = []\n",
    "            container_weight = 0\n",
    "            container_volume = 0\n",
    "            container_dest = None\n",
    "            \n",
    "            for i in range(len(df)):\n",
    "                qty = int(pulp.value(x[i,k]))\n",
    "                if qty > 0:\n",
    "                    item_weight = df.iloc[i]['w'] * qty\n",
    "                    item_volume = df.iloc[i]['v'] * qty\n",
    "                    container_items.append({\n",
    "                        'item_index': i,\n",
    "                        'destination': df.iloc[i]['d'],\n",
    "                        'quantity': qty,\n",
    "                        'weight': item_weight,\n",
    "                        'volume': item_volume\n",
    "                    })\n",
    "                    container_weight += item_weight\n",
    "                    container_volume += item_volume\n",
    "                    container_dest = df.iloc[i]['d']\n",
    "            \n",
    "            if container_items:  # 只添加非空的集装箱\n",
    "                results.append({\n",
    "                    'container_id': k,\n",
    "                    'destination': container_dest,\n",
    "                    'total_weight': container_weight,\n",
    "                    'total_volume': container_volume,\n",
    "                    'items': container_items\n",
    "                })\n",
    "    \n",
    "    return results\n",
    "\n",
    "# 测试数据\n",
    "data = {\n",
    "    'v': [10, 8, 15, 20, 5, 12],\n",
    "    'w': [2, 3, 4, 5, 1, 6],\n",
    "    'd': ['PortX', 'PortY', 'PortX', 'PortY', 'PortX', 'PortY'],\n",
    "    'n': [50, 70, 40, 60, 80, 90],\n",
    "}\n",
    "df = pd.DataFrame(data)\n",
    "\n",
    "# 计算每个目的地的总量\n",
    "print(\"\\n目的地货物统计：\")\n",
    "for dest in df['d'].unique():\n",
    "    dest_df = df[df['d'] == dest]\n",
    "    total_volume = sum(dest_df['v'] * dest_df['n'])\n",
    "    total_weight = sum(dest_df['w'] * dest_df['n'])\n",
    "    print(f\"{dest}: 总体积={total_volume}, 总重量={total_weight}\")\n",
    "\n",
    "# 运行优化\n",
    "print(\"\\n开始优化...\")\n",
    "wt=22\n",
    "vt=71\n",
    "results = optimize_containers(df, wt=wt, vt=vt)\n",
    "\n",
    "if results:\n",
    "    print(f\"\\n总共需要 {len(results)} 个集装箱\")\n",
    "    for container in results:\n",
    "        print(f\"\\n集装箱 {container['container_id']} (目的地: {container['destination']}):\")\n",
    "        print(f\"总重量: {container['total_weight']:.2f}/{wt}\")\n",
    "        print(f\"总体积: {container['total_volume']:.2f}/{vt}\")\n",
    "        print(\"装载的货物:\")\n",
    "        for item in container['items']:\n",
    "            print(f\"- 货物 {item['item_index']}: \"\n",
    "                  f\"{item['quantity']}件, \"\n",
    "                  f\"重量={item['weight']:.2f}, \"\n",
    "                  f\"体积={item['volume']:.2f}\")"
   ],
   "id": "a652e41ce5a32a03",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "目的地货物统计：\n",
      "PortX: 总体积=1500, 总重量=340\n",
      "PortY: 总体积=2840, 总重量=1050\n",
      "\n",
      "开始优化...\n",
      "按体积计算的最小集装箱数: 62\n",
      "按重量计算的最小集装箱数: 64\n",
      "理论最小集装箱数: 64\n",
      "开始求解...\n",
      "求解状态: Optimal\n",
      "\n",
      "总共需要 72 个集装箱\n",
      "\n",
      "集装箱 0 (目的地: PortY):\n",
      "总重量: 18.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 4件, 重量=12.00, 体积=32.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 2 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 3 (目的地: PortX):\n",
      "总重量: 18.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 1件, 重量=2.00, 体积=10.00\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "\n",
      "集装箱 4 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 3件, 重量=6.00, 体积=30.00\n",
      "- 货物 4: 8件, 重量=8.00, 体积=40.00\n",
      "\n",
      "集装箱 5 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 6 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 7 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 56.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 7件, 重量=21.00, 体积=56.00\n",
      "\n",
      "集装箱 8 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 68.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 2件, 重量=6.00, 体积=16.00\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 9 (目的地: PortY):\n",
      "总重量: 18.00/22\n",
      "总体积: 36.00/71\n",
      "装载的货物:\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 10 (目的地: PortX):\n",
      "总重量: 18.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 1件, 重量=2.00, 体积=10.00\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "\n",
      "集装箱 11 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 4: 14件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 12 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 52.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 5件, 重量=15.00, 体积=40.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 13 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 56.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 7件, 重量=21.00, 体积=56.00\n",
      "\n",
      "集装箱 14 (目的地: PortY):\n",
      "总重量: 18.00/22\n",
      "总体积: 68.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 3: 3件, 重量=15.00, 体积=60.00\n",
      "\n",
      "集装箱 15 (目的地: PortX):\n",
      "总重量: 16.00/22\n",
      "总体积: 60.00/71\n",
      "装载的货物:\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "\n",
      "集装箱 16 (目的地: PortX):\n",
      "总重量: 16.00/22\n",
      "总体积: 60.00/71\n",
      "装载的货物:\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "\n",
      "集装箱 17 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 18 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 20 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 22 (目的地: PortX):\n",
      "总重量: 18.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 1件, 重量=2.00, 体积=10.00\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "\n",
      "集装箱 23 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 6件, 重量=12.00, 体积=60.00\n",
      "- 货物 4: 2件, 重量=2.00, 体积=10.00\n",
      "\n",
      "集装箱 24 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 7件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 26 (目的地: PortX):\n",
      "总重量: 16.00/22\n",
      "总体积: 60.00/71\n",
      "装载的货物:\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "\n",
      "集装箱 27 (目的地: PortY):\n",
      "总重量: 20.00/22\n",
      "总体积: 52.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 3: 1件, 重量=5.00, 体积=20.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 28 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 29 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 4: 14件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 30 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 32 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 34 (目的地: PortX):\n",
      "总重量: 18.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 1件, 重量=2.00, 体积=10.00\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "\n",
      "集装箱 35 (目的地: PortX):\n",
      "总重量: 18.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 1件, 重量=2.00, 体积=10.00\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "\n",
      "集装箱 36 (目的地: PortX):\n",
      "总重量: 18.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 1件, 重量=2.00, 体积=10.00\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "\n",
      "集装箱 37 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 39 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 7件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 40 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 41 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 56.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 7件, 重量=21.00, 体积=56.00\n",
      "\n",
      "集装箱 42 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 44 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 7件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 46 (目的地: PortY):\n",
      "总重量: 20.00/22\n",
      "总体积: 52.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 3: 1件, 重量=5.00, 体积=20.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 47 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 49 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 50 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 7件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 51 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 52 (目的地: PortY):\n",
      "总重量: 18.00/22\n",
      "总体积: 68.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 3: 3件, 重量=15.00, 体积=60.00\n",
      "\n",
      "集装箱 54 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 55 (目的地: PortY):\n",
      "总重量: 18.00/22\n",
      "总体积: 36.00/71\n",
      "装载的货物:\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 56 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 57 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 58 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 59 (目的地: PortY):\n",
      "总重量: 18.00/22\n",
      "总体积: 68.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 3: 3件, 重量=15.00, 体积=60.00\n",
      "\n",
      "集装箱 60 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 7件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 62 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 56.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 7件, 重量=21.00, 体积=56.00\n",
      "\n",
      "集装箱 63 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 64 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 4: 14件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 66 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 4: 14件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 67 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 68 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 69 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 73 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 74 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 56.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 7件, 重量=21.00, 体积=56.00\n",
      "\n",
      "集装箱 75 (目的地: PortX):\n",
      "总重量: 16.00/22\n",
      "总体积: 60.00/71\n",
      "装载的货物:\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "\n",
      "集装箱 76 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 77 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 78 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 79 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 68.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 2件, 重量=6.00, 体积=16.00\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 80 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 81 (目的地: PortY):\n",
      "总重量: 18.00/22\n",
      "总体积: 68.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 3: 3件, 重量=15.00, 体积=60.00\n",
      "\n",
      "集装箱 85 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 86 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 52.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 5件, 重量=15.00, 体积=40.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 87 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 4: 14件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 91 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 94 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 95 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n"
     ]
    }
   ],
   "execution_count": 24
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-10T07:08:53.564415Z",
     "start_time": "2025-01-10T07:06:52.953296Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import pulp\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "def optimize_containers(df, wt, vt):\n",
    "    # 获取唯一的目的地\n",
    "    destinations = df['d'].unique()\n",
    "    \n",
    "    # 创建问题\n",
    "    prob = pulp.LpProblem(\"Container_Optimization\", pulp.LpMinimize)\n",
    "    \n",
    "    # 计算需要的最小集装箱数（向上取整）\n",
    "    min_containers_volume = int(np.ceil(sum(df['v'] * df['n']) / vt))\n",
    "    min_containers_weight = int(np.ceil(sum(df['w'] * df['n']) / wt))\n",
    "    min_containers = max(min_containers_volume, min_containers_weight)\n",
    "    max_containers = min_containers * 2\n",
    "    \n",
    "    print(f\"按体积计算的最小集装箱数: {min_containers_volume}\")\n",
    "    print(f\"按重量计算的最小集装箱数: {min_containers_weight}\")\n",
    "    print(f\"理论最小集装箱数: {min_containers}\")\n",
    "    \n",
    "    # 决策变量\n",
    "    # y[k]: 是否使用第k个集装箱\n",
    "    y = pulp.LpVariable.dicts(\"container\",\n",
    "                             range(max_containers),\n",
    "                             cat='Binary')\n",
    "    \n",
    "    # x[i,k]: 货物i分配到集装箱k的数量\n",
    "    x = pulp.LpVariable.dicts(\"allocation\",\n",
    "                             ((i, k) for i in range(len(df)) \n",
    "                              for k in range(max_containers)),\n",
    "                             lowBound=0,\n",
    "                             cat='Integer')\n",
    "    \n",
    "    # d[k,dest]: 集装箱k是否用于目的地dest\n",
    "    d = pulp.LpVariable.dicts(\"destination\",\n",
    "                             ((k, dest) for k in range(max_containers)\n",
    "                              for dest in destinations),\n",
    "                             cat='Binary')\n",
    "    \n",
    "    # 目标函数：最小化使用的集装箱数量\n",
    "    prob += pulp.lpSum(y[k] for k in range(max_containers))\n",
    "    \n",
    "    # 约束条件\n",
    "    # 1. 每种货物必须被完全分配\n",
    "    for i in range(len(df)):\n",
    "        prob += pulp.lpSum(x[i,k] for k in range(max_containers)) == df.iloc[i]['n']\n",
    "    \n",
    "    # 2. 每个集装箱的重量和体积限制\n",
    "    for k in range(max_containers):\n",
    "        # 重量约束\n",
    "        prob += pulp.lpSum(x[i,k] * df.iloc[i]['w'] for i in range(len(df))) <= wt * y[k]\n",
    "        # 体积约束\n",
    "        prob += pulp.lpSum(x[i,k] * df.iloc[i]['v'] for i in range(len(df))) <= vt * y[k]\n",
    "    \n",
    "    # 3. 目的地约束（新版本）\n",
    "    M = sum(df['n'])  # 一个足够大的数\n",
    "    for k in range(max_containers):\n",
    "        # 每个集装箱只能用于一个目的地\n",
    "        prob += pulp.lpSum(d[k,dest] for dest in destinations) <= 1\n",
    "        \n",
    "        # 如果集装箱被使用，必须指定一个目的地\n",
    "        prob += pulp.lpSum(d[k,dest] for dest in destinations) >= y[k]\n",
    "        \n",
    "        # 如果装了某个目的地的货物，对应的d[k,dest]必须为1\n",
    "        for dest in destinations:\n",
    "            dest_items = df[df['d'] == dest].index\n",
    "            prob += pulp.lpSum(x[i,k] for i in dest_items) <= M * d[k,dest]\n",
    "        \n",
    "        # 如果d[k,dest]=1，只能装该目的地的货物\n",
    "        for dest in destinations:\n",
    "            other_dest_items = df[df['d'] != dest].index\n",
    "            prob += pulp.lpSum(x[i,k] for i in other_dest_items) <= M * (1 - d[k,dest])\n",
    "    \n",
    "    # 求解\n",
    "    print(\"开始求解...\")\n",
    "    solver = pulp.PULP_CBC_CMD(msg=True, timeLimit=120)\n",
    "    status = prob.solve(solver)\n",
    "    print(f\"求解状态: {pulp.LpStatus[status]}\")\n",
    "    \n",
    "    if status != pulp.LpStatusOptimal:\n",
    "        print(\"未找到最优解！\")\n",
    "        return None\n",
    "    \n",
    "    # 获取结果\n",
    "    results = []\n",
    "    for k in range(max_containers):\n",
    "        if pulp.value(y[k]) > 0.5:  # 使用了这个集装箱\n",
    "            container_items = []\n",
    "            container_weight = 0\n",
    "            container_volume = 0\n",
    "            container_dest = None\n",
    "            \n",
    "            for i in range(len(df)):\n",
    "                qty = int(pulp.value(x[i,k]))\n",
    "                if qty > 0:\n",
    "                    item_weight = df.iloc[i]['w'] * qty\n",
    "                    item_volume = df.iloc[i]['v'] * qty\n",
    "                    container_items.append({\n",
    "                        'item_index': i,\n",
    "                        'destination': df.iloc[i]['d'],\n",
    "                        'quantity': qty,\n",
    "                        'weight': item_weight,\n",
    "                        'volume': item_volume\n",
    "                    })\n",
    "                    container_weight += item_weight\n",
    "                    container_volume += item_volume\n",
    "                    container_dest = df.iloc[i]['d']\n",
    "            \n",
    "            if container_items:  # 只添加非空的集装箱\n",
    "                results.append({\n",
    "                    'container_id': k,\n",
    "                    'destination': container_dest,\n",
    "                    'total_weight': container_weight,\n",
    "                    'total_volume': container_volume,\n",
    "                    'items': container_items\n",
    "                })\n",
    "    \n",
    "    return results\n",
    "\n",
    "# 测试数据\n",
    "data = {\n",
    "    'v': [10, 8, 15, 20, 5, 12],\n",
    "    'w': [2, 3, 4, 5, 1, 6],\n",
    "    'd': ['PortX', 'PortY', 'PortX', 'PortY', 'PortX', 'PortY'],\n",
    "    'n': [50, 70, 40, 60, 80, 90],\n",
    "}\n",
    "df = pd.DataFrame(data)\n",
    "\n",
    "# 计算每个目的地的总量\n",
    "print(\"\\n目的地货物统计：\")\n",
    "for dest in df['d'].unique():\n",
    "    dest_df = df[df['d'] == dest]\n",
    "    total_volume = sum(dest_df['v'] * dest_df['n'])\n",
    "    total_weight = sum(dest_df['w'] * dest_df['n'])\n",
    "    print(f\"{dest}: 总体积={total_volume}, 总重量={total_weight}\")\n",
    "\n",
    "# 运行优化\n",
    "print(\"\\n开始优化...\")\n",
    "results = optimize_containers(df, wt=22, vt=71)\n",
    "\n",
    "if results:\n",
    "    print(f\"\\n总共需要 {len(results)} 个集装箱\")\n",
    "    for container in results:\n",
    "        print(f\"\\n集装箱 {container['container_id']} (目的地: {container['destination']}):\")\n",
    "        print(f\"总重量: {container['total_weight']:.2f}/{wt}\")\n",
    "        print(f\"总体积: {container['total_volume']:.2f}/{vt}\")\n",
    "        print(\"装载的货物:\")\n",
    "        for item in container['items']:\n",
    "            print(f\"- 货物 {item['item_index']}: \"\n",
    "                  f\"{item['quantity']}件, \"\n",
    "                  f\"重量={item['weight']:.2f}, \"\n",
    "                  f\"体积={item['volume']:.2f}\")"
   ],
   "id": "6d1c190a585aab07",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "目的地货物统计：\n",
      "PortX: 总体积=1500, 总重量=340\n",
      "PortY: 总体积=2840, 总重量=1050\n",
      "\n",
      "开始优化...\n",
      "按体积计算的最小集装箱数: 62\n",
      "按重量计算的最小集装箱数: 64\n",
      "理论最小集装箱数: 64\n",
      "开始求解...\n",
      "求解状态: Optimal\n",
      "\n",
      "总共需要 72 个集装箱\n",
      "\n",
      "集装箱 1 (目的地: PortX):\n",
      "总重量: 17.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 2: 3件, 重量=12.00, 体积=45.00\n",
      "- 货物 4: 5件, 重量=5.00, 体积=25.00\n",
      "\n",
      "集装箱 2 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 4 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 68.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 2件, 重量=6.00, 体积=16.00\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 6 (目的地: PortX):\n",
      "总重量: 18.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "- 货物 4: 2件, 重量=2.00, 体积=10.00\n",
      "\n",
      "集装箱 7 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 8 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 9 (目的地: PortX):\n",
      "总重量: 18.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "- 货物 4: 2件, 重量=2.00, 体积=10.00\n",
      "\n",
      "集装箱 10 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 12 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 56.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 7件, 重量=21.00, 体积=56.00\n",
      "\n",
      "集装箱 13 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 7件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 14 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 15 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 4: 14件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 16 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 17 (目的地: PortX):\n",
      "总重量: 18.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "- 货物 4: 2件, 重量=2.00, 体积=10.00\n",
      "\n",
      "集装箱 18 (目的地: PortY):\n",
      "总重量: 20.00/22\n",
      "总体积: 56.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 3件, 重量=9.00, 体积=24.00\n",
      "- 货物 3: 1件, 重量=5.00, 体积=20.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 19 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 20 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 68.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 2件, 重量=6.00, 体积=16.00\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 21 (目的地: PortX):\n",
      "总重量: 18.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 1件, 重量=2.00, 体积=10.00\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "\n",
      "集装箱 22 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 23 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 25 (目的地: PortY):\n",
      "总重量: 20.00/22\n",
      "总体积: 52.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 3: 1件, 重量=5.00, 体积=20.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 26 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 27 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 29 (目的地: PortX):\n",
      "总重量: 13.00/22\n",
      "总体积: 60.00/71\n",
      "装载的货物:\n",
      "- 货物 2: 1件, 重量=4.00, 体积=15.00\n",
      "- 货物 4: 9件, 重量=9.00, 体积=45.00\n",
      "\n",
      "集装箱 31 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 52.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 5件, 重量=15.00, 体积=40.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 32 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 33 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 52.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 5件, 重量=15.00, 体积=40.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 35 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 37 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 38 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 39 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 43 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 45 (目的地: PortX):\n",
      "总重量: 16.00/22\n",
      "总体积: 60.00/71\n",
      "装载的货物:\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "\n",
      "集装箱 46 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 68.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 2件, 重量=6.00, 体积=16.00\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 47 (目的地: PortX):\n",
      "总重量: 18.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "- 货物 4: 2件, 重量=2.00, 体积=10.00\n",
      "\n",
      "集装箱 48 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 4: 14件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 49 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 52 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 52.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 5件, 重量=15.00, 体积=40.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 53 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 56.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 7件, 重量=21.00, 体积=56.00\n",
      "\n",
      "集装箱 55 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 59 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 60 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 68.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 2件, 重量=6.00, 体积=16.00\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 61 (目的地: PortY):\n",
      "总重量: 18.00/22\n",
      "总体积: 68.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 3: 3件, 重量=15.00, 体积=60.00\n",
      "\n",
      "集装箱 62 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 56.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 7件, 重量=21.00, 体积=56.00\n",
      "\n",
      "集装箱 63 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 68.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 2件, 重量=6.00, 体积=16.00\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 65 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 69 (目的地: PortX):\n",
      "总重量: 17.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 2: 3件, 重量=12.00, 体积=45.00\n",
      "- 货物 4: 5件, 重量=5.00, 体积=25.00\n",
      "\n",
      "集装箱 70 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 71 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 73 (目的地: PortX):\n",
      "总重量: 18.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 1件, 重量=2.00, 体积=10.00\n",
      "- 货物 2: 4件, 重量=16.00, 体积=60.00\n",
      "\n",
      "集装箱 74 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 7件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 77 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 48.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 3件, 重量=9.00, 体积=24.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 79 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 85 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 1件, 重量=2.00, 体积=10.00\n",
      "- 货物 4: 12件, 重量=12.00, 体积=60.00\n",
      "\n",
      "集装箱 86 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 7件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 88 (目的地: PortY):\n",
      "总重量: 18.00/22\n",
      "总体积: 36.00/71\n",
      "装载的货物:\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 89 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 90 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 7件, 重量=14.00, 体积=70.00\n",
      "\n",
      "集装箱 91 (目的地: PortY):\n",
      "总重量: 10.00/22\n",
      "总体积: 40.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "\n",
      "集装箱 93 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 95 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 96 (目的地: PortX):\n",
      "总重量: 16.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 4件, 重量=8.00, 体积=40.00\n",
      "- 货物 2: 2件, 重量=8.00, 体积=30.00\n",
      "\n",
      "集装箱 98 (目的地: PortY):\n",
      "总重量: 21.00/22\n",
      "总体积: 44.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 1件, 重量=3.00, 体积=8.00\n",
      "- 货物 5: 3件, 重量=18.00, 体积=36.00\n",
      "\n",
      "集装箱 100 (目的地: PortX):\n",
      "总重量: 16.00/22\n",
      "总体积: 65.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 2件, 重量=4.00, 体积=20.00\n",
      "- 货物 2: 3件, 重量=12.00, 体积=45.00\n",
      "\n",
      "集装箱 101 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 104 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 64.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 2件, 重量=12.00, 体积=24.00\n",
      "\n",
      "集装箱 108 (目的地: PortY):\n",
      "总重量: 16.00/22\n",
      "总体积: 52.00/71\n",
      "装载的货物:\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 113 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 6件, 重量=12.00, 体积=60.00\n",
      "- 货物 4: 2件, 重量=2.00, 体积=10.00\n",
      "\n",
      "集装箱 114 (目的地: PortX):\n",
      "总重量: 11.00/22\n",
      "总体积: 55.00/71\n",
      "装载的货物:\n",
      "- 货物 4: 11件, 重量=11.00, 体积=55.00\n",
      "\n",
      "集装箱 116 (目的地: PortY):\n",
      "总重量: 22.00/22\n",
      "总体积: 68.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 2件, 重量=6.00, 体积=16.00\n",
      "- 货物 3: 2件, 重量=10.00, 体积=40.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 126 (目的地: PortY):\n",
      "总重量: 20.00/22\n",
      "总体积: 56.00/71\n",
      "装载的货物:\n",
      "- 货物 1: 3件, 重量=9.00, 体积=24.00\n",
      "- 货物 3: 1件, 重量=5.00, 体积=20.00\n",
      "- 货物 5: 1件, 重量=6.00, 体积=12.00\n",
      "\n",
      "集装箱 127 (目的地: PortX):\n",
      "总重量: 14.00/22\n",
      "总体积: 70.00/71\n",
      "装载的货物:\n",
      "- 货物 0: 7件, 重量=14.00, 体积=70.00\n"
     ]
    }
   ],
   "execution_count": 17
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "",
   "id": "81580f3b1dba6c07"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
